package com.example.object;


import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.info.GraphLayout;
import org.openjdk.jol.vm.VM;

/**
 * 对象测试类
 * <p>
 * 公司：德迅科技
 * 作者：wangdi
 * 描述：
 * 日期： 2025/11/14
 *
 * @author wangdi
 */
public class ObjectMemoryDemo {

    public static void main(String[] args) {
        viewArrayObject();
        viewObject();
        viewBaseObjectHeader();
    }

    /**
     * 观察数组对象头。
     *
     * 对于32和64位JVM，对象头大小为12字节，对象头中包含对象hashCode、对象锁、对象类型信息。
     * 对于数组长度都是4字节，但是64位jvm中会多出4字节，多余的4字节是用不到的，默认开启指针压缩会去掉4字节。
     */
    public static void viewArrayObject() {
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        System.out.println("观察数组对象头\n"+ClassLayout.parseInstance(arr).toPrintable());
        System.out.println("观察数组对象内存\n"+ GraphLayout.parseInstance(arr).toPrintable());
    }

    /**
     * 观察对象对象头
     */
    public static void viewObject() {
        Person person = new Person("张三", 18, "男");
        System.out.println("观察对象类\n"+ClassLayout.parseClass(person.getClass()).toPrintable());
        System.out.println("观察对象头\n"+ClassLayout.parseInstance(person).toPrintable());
        System.out.println("观察对象内存\n"+GraphLayout.parseInstance(person).toPrintable());

        // 打印对象地址（十六进制）
        System.out.println("观察对象 address: 0x" + Long.toHexString(VM.current().addressOf(person)));
        // 打印堆内存起始地址（通过 jmap -heap 可获取，或通过 VM 工具类估算）
        System.out.println("观察对象 Heap base address: 0x" + VM.current().details());
    }

    /**
     * 观察基本对象对象头
     */
    public static void viewBaseObjectHeader() {
        System.out.println("观察基本对象\n"+ClassLayout.parseInstance(1).toPrintable());
    }

    public static class Person {
        private String name;
        private int age;
        private String sex;

        public Person(String name, int age, String sex) {
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    }
}
